package org.al.poc.persistence.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;

import javax.persistence.EntityManager;

/**
 * Classe mère de tous les Dao JPA.
 * Elle hérite de la classe Dao principale.
 * @author Jérome
 */
public abstract class DaoJpa<T, ID extends Serializable> implements Dao<T, ID> {


	protected Class<T> classeEntite;
	protected EntityManager em;

	/**
	 * Constructeur père de tous les constructeurs sans paramètres
	 * indispensables au fonctionnement de JPA.
	 */
	@SuppressWarnings("unchecked")
	protected DaoJpa () {
		classeEntite = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}

	/**
	 * Méthode d'attribution du gestionnaire d'entité.
	 * @param entManag le gestionnaire d'entité attribué.
	 */
	public void setEntityManager (EntityManager entManag) {
		em = entManag;
	}

	/**
	 * Méthode de récupération du gestionnaire d'entité.
	 * @return le gestionnaire d'entité à récupérer.
	 */
	protected EntityManager getEntityManager () {
		return em;
	}

	/**
	 * Implémentation de la méthode de récupération d'un élément
	 * par son id pour JPA.
	 * @param id l'id de l'émément.
	 * @return l'élément que l'on souhaite récupérer.
	 * @throws DaoException 
	 */
	@Override
	public T getById(ID id) throws DaoException {
		try {
			return em.find(classeEntite, id);
		} 
		catch (Exception e) {
			throw new DaoException (e.getMessage(), e.getCause());
		}
	}

	/**
	 * Implémentation de la méthode de création d'élément
	 * pour JPA.
	 * @param object l'élément à créer.
	 * @throws DaoException si un élément identique existe 
	 * déjà ou s'il y a un autre problème de persistance.
	 */
	@Override
	public void create(T object) throws DaoException {
		try {
			em.persist(object);
		} 
		catch (Exception e) {
			throw new DaoException (e.getMessage(), e.getCause());
		}
	}

	/**
	 * Implémentation de la méthode de mise jour d'élément
	 * pour JPA.
	 * @param object l'élément à mettre à jour.
	 * @return l'élément mis à jour.
	 * @throws DaoException si aucun élément ne correspond à l'élément cherché ou 
	 * s'il y a un autre problème de persistance.
	 */
	@Override
	public T update(T object) throws DaoException {
		try {
			return em.merge(object);
		} 
		catch (Exception e) {
			throw new DaoException (e.getMessage(), e.getCause());
		}
	}

	/**
	 * Implémentation de la méthode de suppression d'élément
	 * pour JPA.
	 * @param object l'élément à supprimer.
	 * @throws DaoException si aucun élément ne correspond à l'élément cherché ou 
	 * s'il y a un autre problème de persistance.
	 */
	@Override
	public void delete(T object) throws DaoException {
		try {
			em.remove(object);
		} 
		catch (Exception e) {
			throw new DaoException (e.getMessage(), e.getCause());
		}
	}

}
